package cn.jbolt.common.util;
import org.apache.commons.lang3.StringEscapeUtils;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.*;

/**
 * 字符串工具类，继承lang3字符串工具类
 * @author Javen
 * 2016年4月3日
 */
public final class StringUtils extends org.apache.commons.lang3.StringUtils {

	private static final String hexString="0123456789ABCDEF";

	public static String encode(String str){
		String encode=null;
		try {
			encode = URLEncoder.encode(str, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return encode;
	}
	
	/**
	 * 获取UUID，去掉`-`的
	 * @return uuid
	 */
	public static String getUUID () {
		return UUID.randomUUID().toString().replace("-", "");
	}

	 /**
	 * 将字符串中特定模式的字符转换成map中对应的值
	 * 
	 * use: format("my name is ${name}, and i like ${like}!", {"name":"L.cm", "like": "Java"})
	 * 
	 * @param s		需要转换的字符串
	 * @param map	转换所需的键值对集合
	 * @return		转换后的字符串
	 */
	public static String format(String s, Map<String, String> map) {
		StringBuilder sb = new StringBuilder((int)(s.length() * 1.5));
		int cursor = 0;
		for (int start, end; (start = s.indexOf("${", cursor)) != -1 && (end = s.indexOf('}', start)) != -1;) {
			sb.append(s.substring(cursor, start));
			String key = s.substring(start + 2, end);
			sb.append(map.get(StringUtils.trim(key)));
			cursor = end + 1;
		}
		sb.append(s.substring(cursor, s.length()));
		return sb.toString();
	}
	


	/**
	 * 字符串格式化
	 * 
	 * use: format("my name is {0}, and i like {1}!", "L.cm", "java")
	 * 
	 * int long use {0,number,#}
	 * 
	 * @param s 
	 * @param args
	 * @return 转换后的字符串
	 */
	public static String format(String s, Object... args) {
		return MessageFormat.format(s, args);
	}
	
	/**
	 * 替换某个字符
	 * @param str
	 * @param regex
	 * @param args
	 * @return
	 */
	public static String replace(String str,String regex,String... args){
		int length = args.length;
		for (int i = 0; i < length; i++) {
			str=str.replaceFirst(regex, args[i]);
		}
		return str;
	}

	/**
	 * 转义HTML用于安全过滤
	 * @param html
	 * @return
	 */
	public static String escapeHtml(String html) {
		return StringEscapeUtils.escapeHtml4(html);
	}

	/**
	 * 清理字符串，清理出某些不可见字符
	 * @param txt
	 * @return {String}
	 */
	public static String cleanChars(String txt) {
		return txt.replaceAll("[ 　	`·•�\\f\\t\\v]", "");
	}

	// 随机字符串
	private static final String _INT = "0123456789";
	private static final String _STR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
	private static final String _ALL = _INT + _STR;

	private static final Random RANDOM = new Random();

	/**
	 * 生成的随机数类型
	 */
	public static enum RandomType {
		INT, STRING, ALL;
	}

	/**
	 * 随机数生成
	 * @param count
	 * @return
	 */
	public static String random(int count, RandomType randomType) {
		if (count == 0) return "";
		if (count < 0) {
			throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
		}
		char[] buffer = new char[count];
		for (int i = 0; i < count; i++) {
			if (randomType.equals(RandomType.INT)) {
				buffer[i] = _INT.charAt(RANDOM.nextInt(_INT.length()));
			} else if (randomType.equals(RandomType.STRING)) {
				buffer[i] = _STR.charAt(RANDOM.nextInt(_STR.length()));
			}else {
				buffer[i] = _ALL.charAt(RANDOM.nextInt(_ALL.length()));
			}
		}
		return new String(buffer);
	}

	/**
	 * Convert byte[] to hex string.这里我们可以将byte转换成int，然后利用Integer.toHexString(int)来转换成16进制字符串。
	 * @param src byte[] data
	 * @return hex string
	 */
	public static String bytesToHexString(byte[] src){
		StringBuilder stringBuilder = new StringBuilder("");
		if (src == null || src.length <= 0) {
			return null;
		}
		for (int i = 0; i < src.length; i++) {
			int v = src[i] & 0xFF;
			String hv = Integer.toHexString(v);
			if (hv.length() < 2) {
				stringBuilder.append(0);
			}
			stringBuilder.append(hv);
		}
		return stringBuilder.toString();
	}
	/**
	 * Convert hex string to byte[]
	 * @param hexString the hex string
	 * @return byte[]
	 */
	public static byte[] hexStringToBytes(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return null;
		}
		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d = new byte[length];
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
		}
		return d;
	}

	/**
	 * Convert char to byte
	 * @param c char
	 * @return byte
	 */
	private static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);
	}

	/**
	 * 字符串转换为Ascii
	 * @param value
	 * @return
	 */
	public static String stringToAscii(String value,String split)
	{
		StringBuffer sbu = new StringBuffer();
		char[] chars = value.toCharArray();
		for (int i = 0; i < chars.length; i++) {
			if(i != chars.length - 1)
			{
				sbu.append((int)chars[i]).append(split);
			}
			else {
				sbu.append((int)chars[i]);
			}
		}
		return sbu.toString();
	}
	/**
	 * convert ascii string to hex
	 * @param str
	 * @return
     */
	public static String stringToAscii(String str) {

		char[] chars = str.toCharArray();

		StringBuffer hex = new StringBuffer();
		for (int i = 0; i < chars.length; i++) {
			hex.append((int) chars[i]);
		}
		return hex.toString();
	}

	/**
	 * convert  16进制ascii to 10进制string
	 * @param strAscii
	 * @return
     */
	public static String ascsiiToString(String strAscii) {

		StringBuilder sb = new StringBuilder();
		StringBuilder temp = new StringBuilder();

		// 49204c6f7665204a617661 split into two characters 49, 20, 4c...
		for (int i = 0; i < strAscii.length() - 1; i += 2) {

			// grab the hex in pairs
			String output = strAscii.substring(i, (i + 2));
			if (output.equals("00")){
				break;
				//结束标志无效字符
			}
			// convert hex to decimal
			int decimal = Integer.parseInt(output, 16);
			// convert the decimal to character
			sb.append((char) decimal);

			temp.append(decimal);
		}

		return sb.toString();
	}

	/**
	 * 生成16进制累加和校验码
	 *
	 * @param data 除去校验位的数据
	 * @return
	 */
	public static String makeChecksum(String data) {
		if (StringUtils.isEmpty(data)) {
			return "";
		}
		int total = 0;
		int len = data.length();
		int num = 0;
		while (num < len) {
			String s = data.substring(num, num + 2);
			total += Integer.parseInt(s, 16);
			num = num + 2;
		}
		/**
		 * 用256求余最大是255，即16进制的FF
		 */
		int mod = total % 256;
		String hex = Integer.toHexString(mod);
		len = hex.length();
		//如果不够校验位的长度，补0,这里用的是两位校验
		if (len < 2) {
			hex = "0" + hex;
		}
		return hex;
	}

	/**
	 * 返回指定长度的字符串，如果长度不够，则进行补零处理，否则进行截取
	 * @param originalStr 需要补零的字符串
	 * @param requiredLength 需要满足的长度
	 * @param fillType 补零方式 back 向后补0，front 向前补0
	 * @return
	 */
	public static String fillZeroToStr(String originalStr,int requiredLength,String fillType){
		if(org.apache.commons.lang3.StringUtils.isBlank(originalStr)) originalStr="";
		if(originalStr.length()>=requiredLength){
			return originalStr.substring(0,requiredLength);
		}
		StringBuffer sb=new StringBuffer();
		int num=requiredLength-originalStr.length();
		for(int i=0;i<num;i++){
			sb.append("0");
		}
		if("front".equals(fillType)){
			sb.append(originalStr);
		}else{
			sb.insert(0,originalStr);
		}

		return sb.toString();

	}

	/**
	 * 解析一段报文，从指定索引处取指定字节的数据，并显示取回的结果，16进制实际值以及转化为10进制以后的值
	 * @param originalMsg 报文原文
	 * @param startIndex 起始取值索引
	 * @param byteLen 取值的长度（字节）
	 */
	public static void parseMessage(String originalMsg,int startIndex,int byteLen){
		if(StringUtils.isBlank(originalMsg)){
			System.out.println("报文不能为空");
		}
		originalMsg= originalMsg.replace(" ","");
		List<String> msgArray = new ArrayList<String>();
		int i = 0;
		for (i = 0; i < originalMsg.length() - 1; i += 2) {
			msgArray.add(originalMsg.substring(i, i + 2));
		}
		msgArray.add(originalMsg.substring(i));
		int arrayLen=msgArray.size();
		if(startIndex+byteLen> arrayLen){
			System.out.println("报文取值范围错误，报文长度为"+arrayLen+"字节，从索引"+startIndex+"开始最多取"+(arrayLen-startIndex)+"字节的数据！");
		}
		StringBuffer sb=new StringBuffer();
		StringBuffer sb2=new StringBuffer();
		for(int j=0;j<byteLen;j++){
			sb.insert(0,msgArray.get(j+startIndex));
			sb2.append(msgArray.get(j+startIndex));
		}
		String result=sb.toString();
		String result2=sb2.toString();
		System.out.println("报文取值16进制结果为："+result2+",实际值为："+result+"，转化为10进制结果为："+new BigInteger(result, 16));

	}

	public static String encodeStringToHex(String str)
	{
        //根据默认编码获取字节数组
		byte[] bytes=str.getBytes();
		StringBuilder sb=new StringBuilder(bytes.length*2);
        //将字节数组中每个字节拆解成2位16进制整数
		for(int i=0;i<bytes.length;i++)
		{
			sb.append(hexString.charAt((bytes[i]&0xf0)>>4));
			sb.append(hexString.charAt((bytes[i]&0x0f)>>0));
		}
		return sb.toString();
	}

	public static String decodeHexToString(String bytes)
	{
		ByteArrayOutputStream baos=new ByteArrayOutputStream(bytes.length()/2);
        //将每2位16进制整数组装成一个字节
		for(int i=0;i<bytes.length();i+=2)
			baos.write((hexString.indexOf(bytes.charAt(i))<<4 |hexString.indexOf(bytes.charAt(i+1))));
		    return new String(baos.toByteArray());
	}

	/**
	 * 将16进制数高位换到低位，低位换到高位，如0100，换成0001，007b换成7b00,高位在前，低位在后
	 * @param hexString
	 * @return
     */
	public static String lowHighExchange(String hexString){
		String curStr="";
		int max=hexString.length()/2;
		int length=hexString.length();
		StringBuffer result=new StringBuffer();
		for(int i=0;i<max;i++){
			curStr=hexString.substring(length-(i+1)*2,length-i*2);
			result.append(curStr);
		}
		return result.toString();
	}

	public static void main(String[] args) {
		System.out.println(ascsiiToString("007b"));
		System.out.println(lowHighExchange("007b"));
		System.out.println(Integer.toHexString(255));
		String hex=encodeStringToHex("https://xiaolvyun.baidu.com/gold-cup/icafe//space/evnet/dashboard");
		System.out.println(hex);
		String str=decodeHexToString(hex);
		System.out.println(str);




	}
}
